#include "scanner.h"
#include <cctype>
#include <istream>

ostream& operator<<(ostream &o, const Token &t)
{
    o << "( " << t.kind << ", " << t.token << " )";
    return o;
}

Scanner::Scanner(const Table &_table):
table(_table){}

vector<Token> Scanner::do_scan(istream &in)
{
    vector<Token> res;
    int state = 0;
    Token tmp = {"", -1};
    while (in)
    {
        string line;
        getline(in, line);
        line += '\n';

        size_t i = 0;
        while (i < line.size())
        {
            const char &c = line[i];
            if(state == 0 && isspace(c))
            {
                ++i;
                continue;
            }
            int ne_state = table.state(state, c);
            if(ne_state == -1)
            {
                throw "\e[0;31mError: \e[0m"s + line.substr(0, i) +
                "\e[1;31m"s + c + "\e[0m"s + line.substr(i + 1);
            }
            auto flag = table.entry(state, c);
            if(flag.second)
            {
                tmp.token += c;
                ++i;
            }
            if(flag.first == -1)
            {
                state = ne_state;
            }
            else
            {
                tmp.kind = flag.first;
                res.push_back(tmp);
                tmp.token.clear();
                state = 0;
            }
        }
    }
    return res;
}